﻿using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using SharpDX.XAudio2;
using System.Collections.Generic;
using SharpDX.Multimedia;
using ScheduledXAudio2.Structures;

namespace ScheduledXAudio2
{
    public class DrumPatchInstance : IDisposable, INotifyPropertyChanged
    {
        #region Fields
        //SimpleUnit Unit;
        SourceVoice source;
        bool playing;

        #endregion

        #region Properties

        public bool Playing
        {
            get
            { return playing; }
            set
            {
                playing = value;
                NotifyPropertyChanged("Playing");
            }
        }


        #endregion

        #region Constructor

        internal DrumPatchInstance(VoiceSendDescriptor vsd, WaveFormat format, AudioBuffer buffer)
        {
            //SimpleUnit s = new SimpleUnit();
            //WaveFormat f = Marshal.PtrToStructure(format, s);

            source = new SourceVoice(XA2IOFront.DeviceAccessor, format, true);
            source.SetOutputVoices(vsd);
            source.Stop();
            source.SubmitSourceBuffer(buffer, null);
            buffer.Stream.Position = 0;
            source.BufferEnd += new Action<IntPtr>(source_BufferEnd);
            source.Start();
            Playing = true;
        }

        internal DrumPatchInstance(SimpleUnit Unit)
        {
            try
            {
                source = new SourceVoice(XA2IOFront.DeviceAccessor, Unit.Format, true);
                source.SetOutputVoices(Unit.Vsd);
                source.Stop();
                source.SubmitSourceBuffer(Unit.Buffer, null);
                RestStreamPos(Unit.Buffer.Stream);
                source.BufferEnd += new Action<IntPtr>(source_BufferEnd);
                source.Start();
                Playing = true;
            }
            catch (NullReferenceException ex)
            {
                Console.WriteLine(ex.ToString() + " in " + this.ToString());
                return;
            }

        }

        #endregion

        #region Methods

        private void RestStreamPos(SharpDX.DataStream target)
        {
            target.Position = 0;
        }

        #endregion Methods

        #region IDisposable
        public void Dispose()
        {
            source.FlushSourceBuffers();
            source.DestroyVoice();
            source.Dispose();
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Flags "playing" as false so the engine knows this should be disposed.
        /// </summary>
        /// <param name="obj"></param>
        /// 
        void source_BufferEnd(IntPtr obj)
        {
            Playing = false;
        }
        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion

    }


}
